package db

import (
	"dc-news/common/utils"
	"dc-news/dao/model"
	"dc-news/entity"
	"errors"
	"github.com/spf13/cast"
	"go.uber.org/zap"
	"time"
)

// CreateComment 创建评论
func CreateComment(comment *entity.Comments) (err error) {
	err = DB.Create(comment).Error
	if err != nil {
		zap.S().Error("创建评论操作数据库错误: ", err)
	}
	return
}

// GetCommentById 通过id查询评论
func GetCommentById(id int, userID int) (comment *model.Comment, err error) {
	comment = new(model.Comment)
	err = DB.Raw(`
select c.id                                    as comment_id,
       (select count(*)
        from comment_likes cl
        where cl.comment_id = c.id
          and cl.type = 1)                     as like_count,
       (select count(*)
        from comment_likes cl
        where cl.comment_id = c.id
          and cl.type = 2)                     as dislike_count,
       (select comment_likes.type
        from comment_likes
        where comment_likes.user_id = ?
          and comment_likes.comment_id = c.id) as likes,
       @ibc := (select 1
                from comments
                where comments.reply_comment_id = c.id
                limit 1)                       as is_been_commented,
       if(@ibc = 1,
          (select count(*)
           from comments
           where comments.reply_comment_id = c.id),
          0)                                   as commented_count,
       u.id                                    as user_id,
       u.nickname                              as user_nickname,
       u.avatar                                as user_avatar,
       c.content                               as content
from comments c
         join users u on c.user_id = u.id
where c.id = ?
`, userID, id).Scan(comment).Error
	if err != nil {
		zap.S().Error("通过id查询评论操作数据库错误: ", err)
	}
	return
}

// GetNewsCommentsById 通过新闻id获取新闻评论
func GetNewsCommentsById(id int, userId int) (comments *[]model.Comment, err error) {
	comments = new([]model.Comment)
	err = DB.Raw(`
select c.id                                    as comment_id,
       (select count(*)
        from comment_likes cl
        where cl.comment_id = c.id
          and cl.type = 1)                     as like_count,
       (select count(*)
        from comment_likes cl
        where cl.comment_id = c.id
          and cl.type = 2)                     as dislike_count,
       (select comment_likes.type
        from comment_likes
        where comment_likes.user_id = ?
          and comment_likes.comment_id = c.id) as likes,
       @ibc := (select 1
                from comments
                where comments.reply_comment_id = c.id
                limit 1)                       as is_been_commented,
       if(@ibc = 1,
          (select count(*)
           from comments
           where comments.reply_comment_id = c.id),
          0)                                   as commented_count,
       u.id                                    as user_id,
       u.nickname                              as user_nickname,
       u.avatar                                as user_avatar,
       c.content                               as content
from comments c
         join users u on c.user_id = u.id
where c.news_id = ?
  and c.reply_comment_id = 0
`, userId, id).Scan(comments).Error
	if err != nil {
		zap.S().Error("通过新闻id获取新闻评论操作数据库错误: ", err)
	}
	return
}

// GetCommentCommentsById 通过评论id获取评论的评论
func GetCommentCommentsById(id int, userId int) (comments *[]model.Comment, err error) {
	comments = new([]model.Comment)
	err = DB.Raw(`
select c.id                                    as comment_id,
       (select count(*)
        from comment_likes cl
        where cl.comment_id = c.id
          and cl.type = 1)                     as like_count,
       (select count(*)
        from comment_likes cl
        where cl.comment_id = c.id
          and cl.type = 2)                     as dislike_count,
       (select comment_likes.type
        from comment_likes
        where comment_likes.user_id = ?
          and comment_likes.comment_id = c.id) as likes,
       @ibc := (select 1
                from comments
                where comments.reply_comment_id = c.id
                limit 1)                       as is_been_commented,
       if(@ibc = 1,
          (select count(*)
           from comments
           where comments.reply_comment_id = c.id),
          0)                                   as commented_count,
       u.id                                    as user_id,
       u.nickname                              as user_nickname,
       u.avatar                                as user_avatar,
       c.content                               as content
from comments c
         join users u on c.user_id = u.id
where c.reply_comment_id = ?
`, userId, id).Scan(comments).Error
	if err != nil {
		zap.S().Error("通过新闻id获取新闻评论操作数据库错误: ", err)
	}
	return
}

// SetCommentLikesByIdAndType 通过用户id和评论id设置评论赞踩状态
func SetCommentLikesByIdAndType(userId int, commentId int, likesType int) (err error) {
	commentIsExist := false
	DB.Raw("select 1 from comments where id = ?", commentId).Scan(&commentIsExist)
	if !commentIsExist {
		return errors.New("comment is not exist")
	}
	likeIsExist := false
	DB.Raw("select 1 from comment_likes cl where cl.user_id = ? and cl.comment_id = ? limit 1", userId, commentId).Scan(&likeIsExist)
	if likeIsExist {
		return errors.New("has been liked")
	}
	err = DB.Create(&entity.CommentLikes{
		CommentId: commentId,
		UserId:    userId,
		Type:      likesType,
		LikeTime:  time.Now().Unix(),
	}).Error
	if err != nil {
		zap.S().Error("通过用户id和评论id设置评论赞踩状态操作数据库错误: ", err)
	}
	return
}

// CancelLikesCommentById 通过id取消赞/踩
func CancelLikesCommentById(commentId int, userId int) (err error) {
	err = DB.
		Model(&entity.CommentLikes{}).
		Where("comment_id = ? and user_id = ?", commentId, userId).
		Delete(&entity.CommentLikes{}).
		Error
	if err != nil {
		zap.S().Error("通过id取消赞/踩操作数据库错误: ", err)
	}
	return
}

// GetUserCommentListById 获取用户评论列表
func GetUserCommentListById(userId int, p *utils.Pagination) (comments *[]model.UserComment, err error) {
	comments = new([]model.UserComment)
	err = DB.Raw(`
select c.id                                     as comment_id,
       c.news_id                                as news_id,
       (select news.title
        from news
        where news.id = c.news_id)              as news_title,
       c.content                                as content,
       c.reply_comment_id                       as reply_id,
       (select comments.content
        from comments
        where comments.id = c.reply_comment_id) as reply_content
from comments c
where c.user_id = ?
limit ?,?
`, userId, p.Offset, p.Size).Scan(comments).Error
	if err != nil {
		zap.S().Error("获取用户评论列表操作数据库错误: ", err)
		return nil, err
	}
	var count int64
	DB.Model(&entity.Comments{}).Where("user_id = ?", userId).Count(&count)
	p.Total = cast.ToInt(count)
	return
}

// GetUserLikesCommentListById 获取用户点赞评论列表
func GetUserLikesCommentListById(userId int, p *utils.Pagination) (comments *[]model.UserComment, err error) {
	comments = new([]model.UserComment)
	err = DB.Raw(`
select c.id                                     as comment_id,
       c.news_id                                as news_id,
       (select news.title
        from news
        where news.id = c.news_id)              as news_title,
       c.content                                as content,
       c.reply_comment_id                       as reply_id,
       (select comments.content
        from comments
        where comments.id = c.reply_comment_id) as reply_content
from comments c join comment_likes cl on c.id = cl.comment_id
where c.user_id = ?
limit ?,?
`, userId, p.Offset, p.Size).Scan(comments).Error
	if err != nil {
		zap.S().Error("获取用户点赞评论列表操作数据库错误: ", err)
		return nil, err
	}
	var count int64
	DB.Model(&entity.Comments{}).Where("user_id = ?", userId).Count(&count)
	p.Total = cast.ToInt(count)
	return
}

// GetCommentCountById 获取评论数量
func GetCommentCountById(userId int, after int64) int {
	var count int64
	DB.
		Model(&entity.Comments{}).
		Where("user_id = ? and comment_time > ?", userId, after).
		Count(&count)
	return cast.ToInt(count)
}

// GetCommentLikeCount 获取评论点赞数量
func GetCommentLikeCount(userId int, after int64) int {
	var count int64
	DB.
		Model(&entity.CommentLikes{}).
		Where("user_id = ? and type = 1 and like_time > ?", userId, after).
		Count(&count)
	return cast.ToInt(count)
}
